package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.zzyl.common.core.domain.R;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.*;
import com.zzyl.nursing.service.*;
import com.zzyl.nursing.utils.CodeGenerator;
import com.zzyl.nursing.utils.IDCardUtils;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.CheckInMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 入住Service业务层处理
 * 
 * @author alexis
 * @date 2025-06-07
 */
@Service
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService
{
    @Autowired
    private CheckInMapper checkInMapper;

    @Autowired
    private IElderService elderService;
    @Autowired
    private IBedService bedService;
    @Autowired
    private IContractService contractService;
    @Autowired
    private ICheckInConfigService checkInConfigService;


    /**
     * 查询入住
     * 
     * @param id 入住主键
     * @return 入住
     */
    @Override
    public CheckInApplyDto selectCheckInById(Long id)
    {

//        return checkInMapper.selectById(id);
        //总体思路 : 依次取出数据放到对应的成员变量中
        CheckInApplyDto checkInApplyDto = new CheckInApplyDto();
        //1. 取出入住信息内含家属信息
        CheckIn checkIn = checkInMapper.selectById(id);
        checkInApplyDto.setCheckInContractDto(BeanUtil.toBean(checkIn, CheckInContractDto.class));
        //2. 取出老人的信息:
//        Elder elder = elderService.getById(checkInApplyDto.get().);
//        checkInApplyDto.setCheckInElderDto(BeanUtil.toBean(elder, CheckInElderDto.class));


        return null;
    }

    /**
     * 查询入住列表
     * 
     * @param checkIn 入住
     * @return 入住
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn)
    {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn)
    {
        return checkInMapper.insert(checkIn);
    }

    /**
     * 修改入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn)
    {
        return checkInMapper.updateById(checkIn);
    }

    /**
     * 批量删除入住
     * 
     * @param ids 需要删除的入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids)
    {
        return checkInMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除入住信息
     * 
     * @param id 入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id)
    {
        return checkInMapper.deleteById(id);
    }

    // 大思路 :  封装数据到实体类, 补全数据新增
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int applyCheckIn(CheckInApplyDto dto) {
        //从dto取出实体各自对象
        CheckInElderDto elderDto = dto.getCheckInElderDto();
        CheckInContractDto contractDto = dto.getCheckInContractDto();
        CheckInConfigDto configDto = dto.getCheckInConfigDto();
        List<ElderFamilyDto> familyDtos = dto.getElderFamilyDtoList();
        //2. 更新床位状态
        Bed bed = bedService.getById(dto.getCheckInConfigDto().getBedId());
        if (bed==null){
            throw new RuntimeException("床位不存在");
        }
        bed = new Bed();
        bed.setBedStatus(1);
        bed.setId(dto.getCheckInConfigDto().getBedId());
        bedService.updateById(bed);
        // 1. 校验老人是否已入住
        //拿着老人的身份证去查询状态是是不是1启用
        //3. 新增或更新老人
        //思路: 一般我们都是创建一个elder对象,把信息存进去直接save;
        // 转移数据有两种方式: 1. BeanUtils.conpyProperties 需要自己手动创建对象 2.hutool的BeanUtil.toBean直接根据一个对象的属性封装同时创建对象
        Elder elder = BeanUtil.toBean(dto.getCheckInElderDto(), Elder.class);
        //补全数据
        elder.setStatus(1);
        bed = bedService.getById(dto.getCheckInConfigDto().getBedId());
        elder.setBedNumber(bed.getBedNumber());
        elder.setBedId(bed.getId());
        //查询老人是否已经存在
        Elder dbelder = elderService.lambdaQuery().eq(Elder::getIdCardNo, elderDto.getIdCardNo()).eq(Elder::getStatus, 1).one();
        if (dbelder==null){ //新增
            elderService.save(elder);
        }else{
            //修改
            //为什么要有修改? 因为之前住过的老人后来走了,又回来住了,我们是不会删除存过得数据的,有价值;
            if (dbelder.getStatus()==1){
                throw new RuntimeException("老人正在入住中");
            }
            elder.setId(dbelder.getId());
            elderService.updateById(elder);
        }

        //4. 新增签约办理
        //创建合同对象
        Contract contract = BeanUtil.toBean(contractDto, Contract.class);
        //补全数据: 拿补全后的elder对象来补全合同信息
        contract.setElderId(elder.getId());
        contract.setElderName(elder.getName());
        //生成合同编号
        contract.setContractNumber("HT"+ CodeGenerator.generateContractNumber());
        contract.setStartDate(configDto.getStartDate());
        contract.setEndDate(configDto.getEndDate());
        Integer status = configDto.getStartDate().isBefore(LocalDateTime.now())?0:1;
        contract.setStatus(status);
//        contract.setSortOrder();//排序编号
        contractService.save(contract);
        //5. 新增入住信息
        CheckIn checkIn = new CheckIn();
        checkIn.setElderId(elder.getId());
        checkIn.setElderName(elder.getName());
        checkIn.setIdCardNo(elder.getIdCardNo());
        checkIn.setNursingLevelName(configDto.getNursingLevelName());
        checkIn.setStartDate(configDto.getStartDate());
        checkIn.setEndDate(configDto.getEndDate());
        checkIn.setBedNumber(elder.getBedNumber());
        //将家属列表转为JSON字符串
        checkIn.setRemark(JSON.toJSONString(familyDtos));
        checkIn.setStatus(0);
        checkInMapper.insert(checkIn);
        //6. 新增入住配置
        CheckInConfig checkInConfig = BeanUtil.toBean(configDto, CheckInConfig.class);
        checkInConfig.setCheckInId(checkIn.getId());
        checkInConfigService.save(checkInConfig);
        return 1;

    }

    @Override
    public CheckInDetailVo detail(Long id) {//这个id是checkin的id
        //1. 获取配置信息
        // 多表联查 check_in_config check_in; 把数据放到checkInConfigVo
        // 先根据eldeid查checkini
        CheckInConfigVo checkInConfigVo = new CheckInConfigVo();
        CheckIn checkIn = lambdaQuery().eq(CheckIn::getId, id).one();
        CheckInConfig checkInConfig = checkInConfigService.lambdaQuery().eq(CheckInConfig::getCheckInId, checkIn.getId()).one();
        if (checkInConfig!=null){
            //这个老人不需要护理
            BeanUtils.copyProperties(checkInConfig,checkInConfigVo);
        }
        checkInConfigVo.setStartDate(checkIn.getStartDate());
        checkInConfigVo.setEndDate(checkIn.getEndDate());
        checkInConfigVo.setBedNumber(checkIn.getBedNumber());

        // 2. 获取老人信息
        Elder elder = elderService.lambdaQuery().eq(Elder::getId, checkIn.getElderId()).one();
        CheckInElderVo checkInElderVo = BeanUtil.toBean(elder, CheckInElderVo.class);
        checkInElderVo.setAge(IDCardUtils.getAgeByIdCard(elder.getIdCardNo()));

        //3. 获取家属信息
        List<ElderFamilyVo> elderFamilyVoList = JSONUtil.toList(checkIn.getRemark(), ElderFamilyVo.class);
        //4. 获取合同信息(根据老人id)
        Contract contract = contractService.lambdaQuery().eq(Contract::getElderId, checkIn.getElderId()).one();
        CheckInDetailVo checkInDetailVo = new CheckInDetailVo();
        // 5. 封装返回数据
        checkInDetailVo.setCheckInElderVo(checkInElderVo);
        checkInDetailVo.setElderFamilyVoList(elderFamilyVoList);
        checkInDetailVo.setCheckInConfigVo(checkInConfigVo);
        checkInDetailVo.setContract(contract);

        return checkInDetailVo;
    }
}
